3.x "recreation"
*/
-#include <cmath> // for abs
+#include "tpo.h"
+
#include <cstdint> // for uint8_t
#include <cstdio> // for printf, SEEK_CUR, SEEK_SET
+#include <cmath> // for abs
#include <cstring> // for strlen, strncmp
#include <vector> // for vector
#include <QScopedArrayPointer> // for QScopedArrayPointer
#include <QString> // for QString
#include <QStringLiteral> // for qMakeStringPrivate, QStringLiteral
-#include <QVector> // for QVector
#include <QtGlobal> // for qPrintable, Q_UNUSED
-#include "defs.h"
-#include "gbfile.h" // for gbfread, gbfgetc, gbfgetint32, gbfreadbuf, gbfseek, gbfgetdbl, gbfgetint16, gbfclose, gbfgetnativecstr, gbfgetuint16, gbfopen_le, gbfile
+#include "defs.h" // for Waypoint, fatal, route_head, le_read32, waypt_add, track_add_wpt, track_add_head, xfree, xmalloc, doing_rtes, doing_wpts, gb_color, route_add_head, route_add_wpt, unknown_alt, doing_trks
+#include "gbfile.h" // for gbfread, gbfgetc, gbfgetint32, gbfreadbuf, gbfseek, gbfgetdbl, gbfgetint16, gbfclose, gbfgetnativecstr, gbfgetuint16, gbfopen_le
#include "jeeps/gpsmath.h" // for GPS_Math_Known_Datum_To_WGS84_M
#define MYNAME "TPO"
-static char* dumpheader = nullptr;
-
-static
-QVector<arglist_t> tpo2_args = {
-};
-
-static
-QVector<arglist_t> tpo3_args = {
-};
-
-
-static gbfile* tpo_file_in;
-static double track_length;
/*******************************************************************************/
/* READ */
/*******************************************************************************/
-/* Define a global here that we can query from multiple places */
-static float tpo_version = 0.0;
-
/* tpo_check_version_string()
Check the first bytes of the file for a version 3.0 header. */
-static void
-tpo_check_version_string()
+void
+TpoFormatBase::tpo_check_version_string()
{
unsigned char string_size;
}
}
-static void
/* tpo_dump_header_bytes(int header_size)
Write the first header_size bytes of the file to standard output
as a C array definition. */
-tpo_dump_header_bytes(int header_size)
+void
+TpoFormatBase::tpo_dump_header_bytes(int header_size)
{
QByteArray buffer = gbfreadbuf(header_size, tpo_file_in);
Keep reading bytes from the file until the section name is encountered,
then go seek_bytes forwards (+) or backwards (-) to the start of
the section data. */
-static void
-tpo_read_until_section(const char* section_name, int seek_bytes)
+void
+TpoFormatBase::tpo_read_until_section(const char* section_name, int seek_bytes)
{
char byte;
unsigned int match_index = 0;
// that is the only type of data available in the version 2.x TPO
// files.
//
-static void tpo_read_2_x()
+void TpoFormatBase::tpo_read_2_x()
{
char buff[16];
//
// For version 3.x files.
//
-static int tpo_read_int()
+int TpoFormatBase::tpo_read_int()
{
constexpr int debug = 0;
//
// For version 3.x/4.x files.
//
-static int tpo_find_block(unsigned int block_desired)
+int TpoFormatBase::tpo_find_block(unsigned int block_desired)
{
unsigned int block_type;
constexpr int debug = 0;
//
// For version 3.x files.
//
-static Waypoint* tpo_convert_ll(int lat, int lon)
+Waypoint* TpoFormatBase::tpo_convert_ll(int lat, int lon)
{
auto* waypoint_temp = new Waypoint;
return (waypoint_temp);
}
-#define TRACKNAMELENGTH 255
-class StyleInfo
-{
-public:
- QString name;
- uint8_t color[3] {0, 0, 0}; // keep R/G/B values separate because line_color needs BGR
- uint8_t wide{0};
- uint8_t dash{0};
-};
-
// Track decoder for version 3.x/4.x files.
// This block contains tracks (called "freehand routes" in Topo).
-static void tpo_process_tracks()
+void TpoFormatBase::tpo_process_tracks()
{
constexpr int debug = 0; // 0-4 for increasingly verbose output in this subroutine)
track_style -= 1; // STARTS AT 1, whereas style arrays start at 0
// Can be 8/16/32-bit value - never used? length in meters?
- track_length = tpo_read_int();
+ double track_length = tpo_read_int();
//UNKNOWN DATA LENGTH
unsigned int name_length = tpo_read_int();
} // end of tpo_process_tracks
-// Global index to waypoints, needed for routes, filled in by
-// tpo_process_waypoints.
-//
-// For version 3.x files.
-//
-static Waypoint** tpo_wp_index;
-static unsigned int tpo_index_ptr;
-
// Waypoint decoder for version 3.x files.
//
-static void tpo_process_waypoints()
+void TpoFormatBase::tpo_process_waypoints()
{
//printf("Processing Waypoints...\n");
// Map Notes decoder for version 3.x files.
//
-static void tpo_process_map_notes()
+void TpoFormatBase::tpo_process_map_notes()
{
//printf("Processing Map Notes...\n");
// Symbols decoder for version 3.x files.
//
-static void tpo_process_symbols()
+void TpoFormatBase::tpo_process_symbols()
{
//printf("Processing Symbols...\n");
// Text Labels decoder for version 3.x files.
//
-static void tpo_process_text_labels()
+void TpoFormatBase::tpo_process_text_labels()
{
//printf("Processing Text Labels...\n");
// with pointers to waypoint objects by tpo_process_waypoints()
// function above.
//
-static void tpo_process_routes()
+void TpoFormatBase::tpo_process_routes()
{
//printf("Processing Routes...\n");
#ifdef DEAD_CODE_IS_REBORN
// Compass decoder for version 3.x files.
//
-static void tpo_process_compass()
+void TpoFormatBase::tpo_process_compass()
{
// Not implemented yet
// (called "freehand routes" or just "routes" in Topo), "waypoints",
// and "gps-routes". We intend to read all three types.
//
-static void tpo_read_3_x()
+void TpoFormatBase::tpo_read_3_x()
{
if (doing_trks) {
-static void
-tpo_rd_init(const QString& fname)
+void
+TpoFormatBase::tpo_rd_init(const QString& fname)
{
// prepare for an attempt to deallocate memory that may or may not get allocated
}
}
-static void
-tpo_rd_deinit()
+void
+TpoFormatBase::tpo_rd_deinit()
{
// Free the waypoint index, we don't need it anymore.
for (unsigned int i = 0; i < tpo_index_ptr; i++) {
gbfclose(tpo_file_in);
}
-static void
-tpo_read()
+void
+TpoFormatBase::tpo_read()
{
if (tpo_version == 2.0) {
fatal(MYNAME ": gpsbabel can only read TPO versions through 3.x.x\n");
}
}
-
-/* TPO 2.x format can read tracks only */
-ff_vecs_t tpo2_vecs = {
- ff_type_file, /* ff_type_internal */
- { ff_cap_none, ff_cap_read, ff_cap_none },
- tpo_rd_init,
- nullptr,
- tpo_rd_deinit,
- nullptr,
- tpo_read,
- nullptr,
- nullptr,
- &tpo2_args,
- NULL_POS_OPS
-};
-
-/* TPO 3.x format can read waypoints/tracks/routes */
-ff_vecs_t tpo3_vecs = {
- ff_type_file, /* ff_type_internal */
- { ff_cap_read, ff_cap_read, ff_cap_read },
- tpo_rd_init,
- nullptr,
- tpo_rd_deinit,
- nullptr,
- tpo_read,
- nullptr,
- nullptr,
- &tpo3_args,
- NULL_POS_OPS
-};
--- /dev/null
+/*
+ National Geographic Topo! TPO file support.
+ 2.x support contributed to gpsbabel by Steve Chamberlin.
+ 3.x support contributed to gpsbabel by Curt Mills.
+ 4.x files read properly when treated as 3.x (final release was 4.5)
+ track parsing bugs fixed by Steve Eckert in 2012 and 2020
+
+ Topo! version 2.x: Tracks are implemented.
+ Topo! version 3.x/4.x: Reading of Tracks/Waypoints/Routes is
+ implemented. Also extracts Map Notes/
+ Symbols/Text Labels as Waypoints.
+
+ Copyright (C) 2005 Steve Chamberlin, slc at alum.mit.edu
+ Portions Copyright (C) 2006 Curtis E. Mills, archer at eskimo dot com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+
+/*
+ TPO format notes:
+ -----------------
+ Most of the ASCII strings embedded in the text will have a
+ byte-count prepended to the string. Unknown yet whether other
+ fields have this same byte-count, but so far it doesn't look like
+ it.
+
+ New format (3.x and later) files begin with a string byte-count
+ byte and then a string starting with "TOPO! Ver. 3.", like "TOPO!
+ Ver. 3.3.4". Can contain routes/tracks/waypoints, embedded
+ images, Map Notes, Symbols, Text Labels, Compass symbols, and
+ several others.
+
+ Older (pre-3.0) format does not have the above string. Contains
+ only tracks. Waypoints are saved in a separate .TPG file.
+
+ Track parsing has been problematic and may still not be right!
+ See further notes and clues in tpo_process_tracks()
+ (can #define Tracks2012 to revert to pre-2020 code in tpo_process_tracks)
+
+ May contain these strings:
+ Frmt: String:
+ ----- --------------------------------
+ 2.x "CTopoAzimuth"
+ 2.x "CTopoBookmark"
+ 2.x "CTopoGpsRoute". Saved in .tpg files (see tpg.c)
+ 2.x "CTopoRoute". The actual tracks we parse here.
+ 2.x "CTopoSymbol"
+ 2.x/3.x "CTopoText"
+ 2.x "CTopoWaypoint". Saved in .tpg files (see tpg.c)
+ 3.x "Notes"
+ 3.x "PNG." Embedded PNG image containing 2 rows of 40
+ symbols each. Starts with signature: 89 50 4e 47 0d
+ 0a 1a 0a, ends with signature 49 45 4e 44 ae 42 60 82.
+ 3.x "shapes"
+ 3.x "arrows"
+ 3.x "recreation"
+*/
+#ifndef TPO_H_INCLUDED_
+#define TPO_H_INCLUDED_
+
+#include <QString> // for QString
+#include <QVector> // for QVector
+#include <cstdint> // for uint8_t
+#include "defs.h" // for ff_cap, arglist_t, ff_cap_none, ff_cap_read, Waypoint, ff_type, ff_type_file
+#include "format.h" // for Format
+#include "gbfile.h" // for gbfile
+
+
+class TpoFormatBase
+{
+protected:
+ /* Constants */
+
+ static constexpr int TRACKNAMELENGTH = 255;
+
+ /* Types */
+
+ class StyleInfo
+ {
+ public:
+ QString name;
+ uint8_t color[3] {0, 0, 0}; // keep R/G/B values separate because line_color needs BGR
+ uint8_t wide{0};
+ uint8_t dash{0};
+ };
+
+ /* Member Functions */
+
+ void tpo_check_version_string();
+ void tpo_dump_header_bytes(int header_size);
+ void tpo_read_until_section(const char* section_name, int seek_bytes);
+ void tpo_read_2_x();
+ int tpo_read_int();
+ int tpo_find_block(unsigned int block_desired);
+ static Waypoint* tpo_convert_ll(int lat, int lon);
+ void tpo_process_tracks();
+ void tpo_process_waypoints();
+ void tpo_process_map_notes();
+ void tpo_process_symbols();
+ void tpo_process_text_labels();
+ void tpo_process_routes();
+ void tpo_read_3_x();
+ void tpo_rd_init(const QString& fname);
+ void tpo_rd_deinit();
+ void tpo_read();
+
+ /* Data Members */
+
+ char* dumpheader = nullptr;
+ gbfile* tpo_file_in{};
+
+ // Define a global here that we can query from multiple places.
+ float tpo_version = 0.0;
+
+ // Global index to waypoints, needed for routes, filled in by
+ // tpo_process_waypoints.
+ //
+ // For version 3.x files.
+ Waypoint** tpo_wp_index{};
+ unsigned int tpo_index_ptr{};
+};
+
+class Tpo2Format : public Format, private TpoFormatBase
+{
+public:
+ QVector<arglist_t>* get_args() override
+ {
+ return &tpo2_args;
+ }
+
+ ff_type get_type() const override
+ {
+ return ff_type_file;
+ }
+
+ QVector<ff_cap> get_cap() const override
+ {
+ /* TPO 2.x format can read tracks only */
+ /* waypoints, tracks, routes */
+ return { ff_cap_none, ff_cap_read, ff_cap_none };
+ }
+
+ void rd_init(const QString& fname) override
+ {
+ tpo_rd_init(fname);
+ }
+ void read() override
+ {
+ tpo_read();
+ }
+ void rd_deinit() override
+ {
+ tpo_rd_deinit();
+ }
+
+private:
+ /* Data Members */
+
+ QVector<arglist_t> tpo2_args = {};
+};
+
+class Tpo3Format : public Format, private TpoFormatBase
+{
+public:
+ QVector<arglist_t>* get_args() override
+ {
+ return &tpo3_args;
+ }
+
+ ff_type get_type() const override
+ {
+ return ff_type_file;
+ }
+
+ QVector<ff_cap> get_cap() const override
+ {
+ /* TPO 3.x format can read waypoints/tracks/routes */
+ /* waypoints, tracks, routes */
+ return { ff_cap_read, ff_cap_read, ff_cap_read };
+ }
+
+ void rd_init(const QString& fname) override
+ {
+ tpo_rd_init(fname);
+ }
+ void read() override
+ {
+ tpo_read();
+ }
+ void rd_deinit() override
+ {
+ tpo_rd_deinit();
+ }
+
+private:
+ /* Data Members */
+
+ QVector<arglist_t> tpo3_args = {};
+};
+#endif // TPO_H_INCLUDED_